/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  map.h
 *        \brief  This is a general-purpose C language map module, with common value structure
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.1.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __map_H
#define __map_H

#include "iterator.h"
#include "config/map_cfg.h"

/* map key type define */
typedef struct 
{
    void* address;
    int size;
} MAP_KEY, map_key_t;

/** 
 *  \brief the parameter transform to key
 *  \param[in] map: map handler
 *  \param[in] key: any type of key
 *  \return address of key
 */
typedef void* (*map_key_trans_t)(void* map, ...);

/** 
 *  \brief element traverse function
 *  \param[in] key: the key of the element in the map
 *  \param[in] value: address of value
 *  \return none
 */
typedef void (*map_traverse_t)(map_key_t key, void* value);

/* map type define */
typedef struct 
{
    VOBJECT parent;                     /* parent object */
    void *nil;                          /* nil node */
    int ktpye;                          /* entity or pointer @ref MAP_KEY_TYPE */
    int ksize;                          /* size of key */
    map_key_trans_t trans;              /* the parameter transform to key */
} MAP, *map_t;


/** 
 *  \brief clear all nodes under the map
 *  \param[in] map: map handler
 *  \return none
 */
void map_clear(map_t map);

/** 
 *  \brief get the size of map
 *  \param[in] map: map handler
 *  \return size of map
 */
int map_size(map_t map);

/** 
 *  \brief get the address of item value from map
 *  \param[in] map: map handler
 *  \param[in] key: key
 *  \return address of map value or map_error(): fail
 */
void* map_data(map_t map, map_key_t key);

/** 
 *  \brief swap two map
 *  \param[in] map: map handler
 *  \param[in] swap: map handler of swap
 *  \return none
 */
void map_swap(map_t map, map_t swap);

/** 
 *  \brief traverse value in map
 *  \param[in] map: map handler
 *  \param[in] traverse: traverse function
 *  \return none
 */
void map_traverse(map_t map, map_traverse_t traverse);

/** 
 *  \brief error return value
 *  \param[in] map: map handler
 *  \return error pointer
 */
void* map_error(map_t map);

/** 
 *  \brief macro definition method for creating map
 *  \param[in] key_type: tpye of key(e.g int char)
 *  \param[in] value_type: tpye of value(e.g int char)
 *  \return map handler
 */
#define map(key_type, value_type) ( \
    __fun_map_create( \
        sizeof(value_type), \
        MK_TYPE(key_type), \
        sizeof(key_type), \
        MK_TRANS(key_type) \
    ) \
)

/** 
 *  \brief macro definition method for delete map
 *  \param[in] map: map handler
 *  \return none
 */
#define _map(map) do { \
    __fun_map_delete((map)); \
    (map)=NULL; \
} while(0)

/** 
 *  \brief insert value into the map according to the key
 *  \param[in] map: map handler
 *  \param[in] key: key
 *  \param[in] value: address of map value
 *  \return 1: success or 0: fail
 */
#define map_insert(map, key, value) ( \
    __fun_map_insert( \
        (map), \
        *(map_key_t *)((map)->trans((map), (key))), \
        (value) \
    ) \
)

/** 
 *  \brief erase value from map according to key
 *  \param[in] map: map handler
 *  \param[in] key: key
 *  \return 1: success or 0: fail
 */
#define map_erase(map, key) ( \
    __fun_map_erase( \
        (map), \
        *(map_key_t *)((map)->trans((map), (key))) \
        ) \
)

/** 
 *  \brief find key from map
 *  \param[in] map: map handler
 *  \param[in] key: key
 *  \return 1: success or 0: fail
 */
#define map_find(map, key) ( \
    __fun_map_find( \
        (map), \
        *(map_key_t *)((map)->trans((map), (key))) \
    ) \
)

/** 
 *  \brief macro definition method for get front item of map
 *  \param[in] map: map handler
 *  \param[in] type: tpye of item
 *  \param[in] key: key
 *  \return reference to the specified item
 */
#define map_at(map, type, key) ( \
    *(type *)map_data( \
        (map), \
        *(map_key_t *)((map)->trans((map), (key))) \
    ) \
)

/* temp method, not used directly */
map_t __fun_map_create(int value_size, int ktpye, int ksize, void* trans);
void __fun_map_delete(map_t map);
int __fun_map_insert(map_t map, map_key_t key, void* value);
int __fun_map_erase(map_t map, map_key_t key);
int __fun_map_find(map_t map, map_key_t key);

#endif 
